<?php
/**
 * 语言常量
 *
 * @author Zeon <scplay@gmail.com>
 * @date 2018/6/4 9:18
 * @copyright PanxSoft Inc.
 */

namespace App\Services\Locale;


use Illuminate\Support\Str;
use Tests\Unit\Services\Locale\LanguageTest;

class Language
{
    /**
     * 常量名应与目录 resources\lang\{dir_name} 中的 dir_name 对应
     */
    const ZH_CN = "zh-CN";
    const EN = "en";
    const ZH_HK = 'zh-HK';

    const CHINESE = '中文';
    const ENGLISH = '英文';
    const HONGKONG = '香港繁体中文';

    const LANGUAGE = [
        ['id' => self::ZH_CN, 'name' => self::CHINESE],
        ['id' => self::EN, 'name' => self::ENGLISH],
        ['id' => self::ZH_HK, 'name' => self::HONGKONG],
    ];

    public static function default(): string
    {
        return self::ZH_CN;
    }

    /**
     * @return bool
     */
    public static function appIsCN(): bool
    {
        return app()->getLocale() === self::ZH_CN;
    }

    /**
     * 返回对应语言当前数据库应显示的 name 的 column
     *
     * @return string
     */
    public static function getLocalNameColumn(): string
    {
        $name = Language::appIsCN() ? 'name' : 'const';

        return $name.' as name'; // 中英文切换
    }

    /**
     * @return string
     */
    public static function getLocalNameOrConst(): string
    {
        $name = Language::appIsCN() ? 'name' : 'const';

        return $name;
    }

    /**
     * @param $lang
     */
    public static function setAppLocale(?string $lang): void
    {
        if (config('pkx.force_locale')) {
            app()->setLocale(config('pkx.force_locale'));
            return;
        }

        $language = self::normalizeLanguageCode($lang);

        app()->setLocale($language);
    }

    /**
     * @example
     *      'zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,fr;q=0.6,zh-TW;q=0.5'
     *   => 'zh-CN'
     *
     * @test
     *
     * @param string|null $header_lang
     *
     * @return array|string
     */
    public static function normalizeHeaderLanguage(string $header_lang = null): ?string
    {
        if (! $header_lang) return null;

        $locale_weight = head(explode(',', $header_lang));

        $locale_lang = head(explode(';', $locale_weight));

        return $locale_lang;
    }

    /**
     * => ['en', 'zh-CN', 'zh-HK' ...]
     *
     * @return array
     */
    public static function localDirNames(): array
    {
        return array_map(function ($path) {
            return pathinfo($path, PATHINFO_BASENAME);
        }, glob(base_path('resources/lang/*'), GLOB_ONLYDIR));
    }

    /**
     * 登录时，获取用户的语言信息。
     * @return string
     */
    public static function getLoginLanguageCode()
    {
        $request = request();

        $code = $request->lang
            ?: $request->language
            ?: self::normalizeHeaderLanguage($request->header('Accept-Language'));

        return self::normalizeLanguageCode($code);
    }

    /**
     * @param $code
     * @return string
     */
    public static function normalizeLanguageCode($code)
    {
        $lower_str_code = mb_strtolower($code);

        if (Str::contains($lower_str_code, 'en')) {
            return Language::EN;
        } else if (Str::contains($lower_str_code, 'hk')) {
            return Language::ZH_HK;
        } else if (Str::contains($lower_str_code, 'cn')) {
            return Language::ZH_CN;
        } else if (Str::contains($lower_str_code, 'tw')) {
            return Language::ZH_HK;
        } else {
            return Language::ZH_CN;
        }
    }

    /**
     * @param string|array $language_key
     * @param string $fallback_locale
     *
     * @return string - set locale string
     */
    public static function setLocaleFromRequest($language_key,
                                                string $fallback_locale = 'zh-cn'): string
    {
        $set_lang = '';
        foreach ((array) $language_key as $key) {
            $language = request()->get($key);
            if ($language) {
                $set_lang = self::normalizeLanguageCode($language);
            }
        }

        if (! $set_lang) {
            $set_lang = $fallback_locale;
        }

        app()->setLocale($set_lang);

        return $set_lang;
    }
}